#include "PrecompiledHeaders.h"
#include "MenuLevelSelect.h"

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////// GAME STATE FUNCTIONS ///////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////

MenuLevelSelect::MenuLevelSelect()
{
	levelIterator = resources->levels.begin();
}

void MenuLevelSelect::enter(void)
{
    // stick the bgm on if not already
    if(!resources->audio->isPlayingMenuBGM()) {
        resources->audio->playMenuBGM();
    }
    
    // set cameras to render through
    resources->render_window->getViewport(0)->setCamera(resources->main_gui_camera);
    if(resources->config->isTriScreen())
    {
        resources->render_window->getViewport(1)->setCamera(resources->left_gui_camera);
        resources->render_window->getViewport(2)->setCamera(resources->right_gui_camera);
    }
    
    // Shows mouse
    CEGUI::MouseCursor::getSingleton().show();
    // Loads the MainMenu.layout script which places all of the main menu buttons on the screen
    CEGUI::Window* levelSelectionSheet = CEGUI::WindowManager::getSingletonPtr()->loadWindowLayout("LevelSelection.layout");
    resources->GUISystem->setGUISheet(levelSelectionSheet);
    // Sets up the level iterator to retrieve level info
    setLevelImage();
    // Attaches events to the Level Selection Menu buttons
    subscribeImageButton("LevelSelection/LeftArrow", &MenuLevelSelect::clickLeftArrow);
	subscribeImageButton("LevelSelection/LevelImage", &MenuLevelSelect::clickLevelImage);
    subscribeImageButton("LevelSelection/RightArrow", &MenuLevelSelect::clickRightArrow);
	subscribeButton("LevelSelection/BackButton", &MenuLevelSelect::clickBackButton, &MenuLevelSelect::hoverBackButton, &MenuLevelSelect::offBackButton);
	// Initialises the menu index
    winIterator = activeWindows.begin();
    currentState = mlsNORMAL;
}

// Calls the enter function to redraw the GUI after being popped back to
void MenuLevelSelect::resume(void)
{
    popGameState();
}

void MenuLevelSelect::exit(void)
{
    CEGUI::MouseCursor::getSingleton().hide();
    CEGUI::WindowManager::getSingleton().destroyAllWindows();
	activeWindows.clear();
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////// EVENT HANDLER FUNCTIONS ////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// Returns to main menu by popping the level selection menu state
bool MenuLevelSelect::clickBackButton(const CEGUI::EventArgs &e)
{
    resources->audio->playSource(AUDIO_MENU_CLICK);
	unsubscribeButton("LevelSelection/BackButton");
    currentState = mlsQUIT;
    popGameState();
    return true;
}

// Changes the appearance of the back button to signify the mouse hovering over the button
bool MenuLevelSelect::hoverBackButton(const CEGUI::EventArgs &e)
{
    resources->audio->playSource(AUDIO_MENU_OVER);
    setWindowText("LevelSelection/BackButton", "[back]");
    return true;
}

// Resets the appearance of the back button to signify the mouse cursor leaving the button area
bool MenuLevelSelect::offBackButton(const CEGUI::EventArgs &e)
{
    setWindowText("LevelSelection/BackButton", "back");
    return true;
}

// Retrieves the previous level from the iterator
bool MenuLevelSelect::clickLeftArrow(const CEGUI::EventArgs &e)
{
    if (levelIterator == resources->levels.begin()) {
		levelIterator = resources->levels.end();
	}
	levelIterator--;
	if(levelIterator->isLocked()) {
        return clickLeftArrow(e);
    }
    resources->audio->playSource(AUDIO_MENU_CLICK);
	setLevelImage();
    return true;
}

// Retrieves the next level from the iterator
bool MenuLevelSelect::clickRightArrow(const CEGUI::EventArgs &e)
{
	levelIterator++;
	if (levelIterator == resources->levels.end()) {
		levelIterator = resources->levels.begin();
	}
	if(levelIterator->isLocked()) {
	    return clickRightArrow(e);
	}
	resources->audio->playSource(AUDIO_MENU_CLICK);
	setLevelImage();
    return true;
}

// Begins loading the level by pushing the load state on
bool MenuLevelSelect::clickLevelImage(const CEGUI::EventArgs &e)
{
    resources->audio->playSource(AUDIO_MENU_CLICK);
	CEGUI::MouseCursor::getSingleton().hide();
    popGameState();
    return true;
}

// Plays the audio associated with hovering over a clickable button
bool MenuLevelSelect::hoverNoise(const CEGUI::EventArgs &e)
{
    resources->audio->playSource(AUDIO_MENU_OVER);
    return true;
}

// Changes the level image and level name based upon the current level in the iterator
void MenuLevelSelect::setLevelImage()
{
	CEGUI::Window *levelImage = CEGUI::WindowManager::getSingletonPtr()->getWindow("LevelSelection/LevelImage");
	resources->current_level = &(*levelIterator);
	levelImage->setProperty("NormalImage", "set:Levels image:" + resources->current_level->normal_image);
	levelImage->setProperty("HoverImage", "set:Levels image:" + resources->current_level->hover_image);
	levelImage->setProperty("PushedImage", "set:Levels image:" + resources->current_level->normal_image);
	setWindowText("LevelSelection/LevelName", resources->current_level->level_name);
}

bool MenuLevelSelect::keyPressed(const OIS::KeyEvent & e)
{
    CEGUI::System *sys = CEGUI::System::getSingletonPtr();
    sys->injectKeyDown(e.key);
    sys->injectChar(e.text);
    
	switch (e.key)
    {
        case OIS::KC_ESCAPE:
            currentState = mlsQUIT;
            MenuState::popGameState();
            break;
		case OIS::KC_LEFT:
			prevButton();
			break;
		case OIS::KC_UP:
			prevButton();
			break;
		case OIS::KC_RIGHT:
			nextButton();
			break;
		case OIS::KC_DOWN:
			nextButton();
			break;
		case OIS::KC_RETURN:
			clickButton();
			break;
        default:
            break;
    }
    
    return true;
}
